6.11. Strangler Fig
Strangler Fig
Происхождение термина и метафора
Название «Strangler Fig» (инжир-душитель) происходит из биологии. В тропических лесах некоторые виды фикусов начинают свой рост как эпифиты на других деревьях. Сначала они опираются на хозяина, чтобы добраться до солнечного света. Со временем их корни спускаются к земле, укореняются и начинают обвивать ствол дерева-носителя. Постепенно эти корни смыкаются вокруг ствола, ограничивая доступ питательных веществ и влаги. В конечном итоге старое дерево погибает и разрушается, а новое продолжает расти на его месте, полностью заняв пространство.
Эта природная модель легла в основу архитектурного паттерна, предложенного Мартином Фаулером в 2004 году. Он описал подход, при котором новая система развивается вокруг существующей, постепенно замещая её функциональность, пока старая система не станет ненужной и не будет отключена.
Суть паттерна Strangler Fig
Strangler Fig — это методология поэтапной замены устаревшей или монолитной системы новой архитектурой без полной остановки текущего бизнеса. Основная идея заключается в том, чтобы не переписывать всё сразу, а создавать новые компоненты параллельно с уже работающими, направляя трафик постепенно от старого к новому.
Такой подход позволяет избежать рисков, связанных с «большим переключением» — ситуацией, когда после длительной разработки новая система внезапно вводится в эксплуатацию, а любая ошибка приводит к масштабным сбоям. Strangler Fig минимизирует такие риски за счёт инкрементальной миграции.
Контекст применения: монолитные системы
Монолитные архитектуры характеризуются тем, что всё приложение представляет собой единый исполняемый модуль. Все компоненты — пользовательский интерфейс, бизнес-логика, работа с данными — тесно связаны и развернуты вместе. Такие системы часто возникают естественным путём на ранних этапах развития продукта, когда скорость вывода на рынок важнее гибкости.
Со временем монолиты становятся трудно поддерживаемыми. Изменения в одной части кода могут непредсказуемо влиять на другие. Развертывание требует обновления всего приложения целиком, даже если изменена лишь малая часть. Команды разработчиков вынуждены координировать свои действия через общую кодовую базу, что замедляет темпы работы.
Когда монолит достигает критического размера, организация сталкивается с необходимостью рефакторинга или полной перестройки архитектуры. Полный переписывание — дорогостоящий и рискованный путь. Strangler Fig предлагает альтернативу: не уничтожать монолит, а обрастать его новыми сервисами, постепенно перенося ответственность.
Архитектурные принципы Strangler Fig
Основной элемент реализации паттерна — маршрутизатор или шлюз, который управляет потоком запросов между старой и новой системами. Этот маршрутизатор может быть реализован как обратный прокси, API-шлюз или часть инфраструктурного уровня (например, с помощью Kubernetes Ingress или Service Mesh).
На начальном этапе весь трафик направляется в монолит. По мере того как разрабатываются и тестируются новые микросервисы или модули, маршрутизатор начинает перенаправлять определённые типы запросов к новым компонентам. Например, запросы, связанные с управлением пользователями, могут идти в новый сервис, а остальные — по-прежнему в монолит.
Важно, чтобы новый компонент обеспечивал ту же функциональность, что и заменяемая часть монолита, и соответствовал внешним контрактам (API, форматы данных, поведение ошибок). Это гарантирует совместимость и прозрачность для клиентов.
Этапы миграции по модели Strangler Fig
-
Анализ и картирование
Первым шагом является детальное изучение монолита: какие функции он выполняет, как организованы внутренние зависимости, какие модули наиболее изолированы. Цель — выделить границы, по которым можно безопасно вырезать функциональность. Часто используются техники Domain-Driven Design (DDD), такие как выявление bounded contexts. -
Настройка маршрутизации
Внедряется механизм, способный перенаправлять запросы. Это может быть простой reverse proxy (например, Nginx) или более сложное решение, поддерживающее правила на основе заголовков, путей URL или даже содержимого тела запроса. -
Разработка первого нового компонента
Выбирается наименее рискованная, но значимая функция для миграции. Обычно это автономный модуль с чёткими входами и выходами. Новый компонент разрабатывается независимо, с собственной базой данных или изолированным доступом к общей. -
Параллельное выполнение и валидация
На этом этапе возможен запуск старой и новой логики одновременно — например, с помощью паттерна «shadow traffic» или «canary release». Результаты сравниваются, чтобы убедиться в корректности новой реализации. -
Переключение трафика
После успешной валидации маршрутизатор направляет все соответствующие запросы в новый компонент. Старая часть монолита становится неактивной, хотя код остаётся в репозитории. -
Удаление мёртвого кода
Когда уверенность в стабильности новой системы высока, старый код удаляется. Это важный шаг, так как он снижает технический долг и упрощает дальнейшее сопровождение. -
Повторение цикла
Процесс повторяется для следующих модулей, пока монолит не будет полностью заменён или сведён к минимальному ядру.
Преимущества подхода
Strangler Fig обеспечивает непрерывность бизнеса. Система остаётся работоспособной на всех этапах миграции. Команды могут выпускать изменения небольшими порциями, получая быструю обратную связь. Риски распределены во времени, а не сконцентрированы в одном моменте запуска.
Подход позволяет применять современные технологии только там, где это необходимо. Например, один сервис может быть написан на Go, другой — на Node.js, третий — на .NET, в то время как монолит остаётся на Java. Это даёт гибкость в выборе стека под конкретную задачу.
Также Strangler Fig способствует культурным изменениям в организации. Команды учатся работать с независимыми сервисами, внедряют DevOps-практики, автоматизируют тестирование и развертывание. Миграция становится не просто техническим проектом, а трансформацией процессов.
Технические вызовы
Одна из главных сложностей — управление данными. Монолит обычно использует единую базу данных. При выделении нового сервиса возникает вопрос: как разделить данные? Варианты включают:
- Создание отдельной базы данных для нового сервиса и синхронизацию с основной через события (event-driven replication).
- Использование общей базы, но с чётким разделением схем (например, разные схемы или префиксы таблиц).
- Постепенный перенос данных с последующим отключением старых таблиц.
Важно избегать двойной записи (dual writes), так как она легко приводит к рассогласованию данных при сбоях.
Другая проблема — транзакционная целостность. В монолите операции над несколькими сущностями могут быть завершены в рамках одной транзакции. В распределённой системе это невозможно. Здесь применяются паттерны Saga или компенсирующие транзакции.
Также требуется тщательное логирование и мониторинг. Поскольку запрос может проходить через несколько систем, необходимо отслеживать его путь (distributed tracing), чтобы быстро находить узкие места и ошибки.
Инструменты и технологии
Для реализации Strangler Fig часто используются:
- API Gateway: Kong, Apigee, AWS API Gateway, Traefik — для маршрутизации запросов.
- Service Mesh: Istio, Linkerd — для управления трафиком на уровне сервисов, включая канареечные релизы и отказоустойчивость.
- Message Brokers: Kafka, RabbitMQ, NATS — для асинхронной коммуникации и синхронизации данных.
- Feature Flags: LaunchDarkly, Split — для гибкого включения/отключения функций без деплоя.
- Observability Tools: Prometheus, Grafana, Jaeger, OpenTelemetry — для мониторинга и трассировки.
Инфраструктурная автоматизация (CI/CD, IaC) играет ключевую роль. Без неё частые деплои новых компонентов становятся обременительными.
Когда Strangler Fig не подходит
Подход требует времени и дисциплины. Если бизнес нуждается в срочной замене системы из-за критических уязвимостей или невозможности масштабирования, Strangler Fig может оказаться слишком медленным.
Также он менее эффективен, если монолит настолько тесно связан, что невозможно выделить чёткие границы. В таких случаях сначала требуется внутренний рефакторинг — декомпозиция кода без изменения архитектуры, чтобы подготовить почву для будущей миграции.
Наконец, Strangler Fig предполагает наличие команды, способной поддерживать две системы одновременно. Это увеличивает краткосрочные затраты, хотя и снижает долгосрочные риски.